package com.zhiche.lisa.integration.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zhiche.lisa.core.enums.IntegrationURIEnum;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.supports.RestfulResponse;
import com.zhiche.lisa.core.utils.HttpClientUtil;
import com.zhiche.lisa.core.utils.qiniu.util.QiniuUtils;
import com.zhiche.lisa.integration.config.IntegrationProperties;
import com.zhiche.lisa.integration.dao.mapper.ImportLogHistoryMapper;
import com.zhiche.lisa.integration.dao.mapper.PushSubSystemMapper;
import com.zhiche.lisa.integration.dao.model.ImportLogHistory;
import com.zhiche.lisa.integration.dao.model.PushSubSystem;
import com.zhiche.lisa.integration.dto.order.ShipmentDTO;
import com.zhiche.lisa.integration.inteface.otm.OtmShipmentParse;
import com.zhiche.lisa.integration.inteface.otm.OtmShipmentService;
import com.zhiche.lisa.integration.service.IImportLogHistoryService;
import com.zhiche.lisa.integration.service.IPushSubSystemService;
import jdk.nashorn.internal.ir.IfNode;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 接口数据推送子系统 服务实现类
 * </p>
 *
 * @author zhaoguixin
 * @since 2018-07-30
 */
@Service
public class PushSubSystemServiceImpl extends ServiceImpl<PushSubSystemMapper, PushSubSystem> implements IPushSubSystemService {

    private Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    @Autowired private IntegrationProperties properties;
    @Autowired private IImportLogHistoryService importLogHistoryService;
    @Autowired private OtmShipmentService otmShipmentService;
    @Autowired
    private ImportLogHistoryMapper importLogHistoryMapper;
    @Autowired
    private PushSubSystemMapper pushSubSystemMapper;

    @Override
    public void pushToSubSystem(Object dto, String type) {
        if (Objects.isNull(dto)) throw new BaseException("数据不能为空！");
        List<PushSubSystem> pushSubSystemList = listPushSubSystem(type);
        String dtoJson = JSON.toJSONString(dto);
        for (PushSubSystem pushSubSystem : pushSubSystemList) {
            String result = null;
            try {
                //推送子系统
                result = HttpClientUtil.postJson(pushSubSystem.getUrl(), null , dtoJson, pushSubSystem.getSocketTimeOut());
            } catch (Exception e) {
                LOGGER.error("指令推送子系统：{}，地址：{}，失败！原因：{},参数：{}", pushSubSystem.getCode(), pushSubSystem.getUrl(), e, dtoJson);
            }
            if (!StringUtils.isEmpty(result)) {
                RestfulResponse restfulResponse = new RestfulResponse<>(0, "成功", null);
                try {
                    restfulResponse = JSON.parseObject(result,
                            new TypeReference<RestfulResponse>() {
                            });
                } catch (Exception ex) {
                    restfulResponse.setCode(-1);
                    restfulResponse.setMessage(ex.getMessage());
                }

                if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
                    LOGGER.info("指令推送子系统：{}，地址：{}，成功！参数：{}",
                            pushSubSystem.getName(), pushSubSystem.getUrl(), dtoJson);
                } else {
                    LOGGER.error("指令推送子系统：{}，地址：{}，失败！原因：{},参数：{}",
                            pushSubSystem.getName(), pushSubSystem.getUrl(), restfulResponse.getMessage(), dtoJson);
                }
            } else {
                LOGGER.error("指令推送子系统：{}，地址：{}，失败！参数：{}",
                        pushSubSystem.getName(), pushSubSystem.getUrl(), dtoJson);
            }
        }
    }

    @Override
    public void pushToSubSystemNew(Object dto, String type,Date startDate,String shipmentXml,String shipmentId, Long senderTransmissionNo) {
        if (Objects.isNull(dto)) throw new BaseException("数据不能为空！");
        List<PushSubSystem> pushSubSystemList = listPushSubSystem(type);
        String dtoJson = JSON.toJSONString(dto);
        toSonSys(type, startDate, shipmentXml, shipmentId, pushSubSystemList, dtoJson, senderTransmissionNo);
    }

    public void toSonSys(String type, Date startDate, String shipmentXml, String shipmentId, List<PushSubSystem> pushSubSystemList, String dtoJson, Long transmissionNo) {
        for (PushSubSystem pushSubSystem : pushSubSystemList) {
            Date endDate;
            endDate = new Date();
            ImportLogHistory importLogHistory = new ImportLogHistory();
            importLogHistory.setTargetSys(pushSubSystem.getCode());
            importLogHistory.setSourceSys("otm");
            importLogHistory.setSourceKey(shipmentId);
            importLogHistory.setType(type);
            importLogHistory.setImportStartTime(startDate);
            importLogHistory.setImportEndTime(endDate);
            importLogHistory.setTransmissionNo(transmissionNo);
//        new Thread(() -> {
            LOGGER.info("开始保存导入日志---------------");
            otmShipmentService.updateLogHistory(importLogHistory, shipmentXml);
            LOGGER.info("完成日志保存---------------");
//        }).start();

            //指令下发失败，重新推送，加上第一次推送，总共需要推送三次
            this.pushFailRepeatPush(pushSubSystem, dtoJson, importLogHistory);

      /*      if ("error".equals(importLogHistory.getImportStatus())) {
                LOGGER.info("指令下发失败，第{}次推送", 2);
                this.pushFailRepeatPush(pushSubSystem, dtoJson, importLogHistory);
                if ("error".equals(importLogHistory.getImportStatus())) {
                    LOGGER.info("指令下发失败，第{}次推送", 3);
                    this.pushFailRepeatPush(pushSubSystem, dtoJson, importLogHistory);
                }
                LOGGER.info("指令下发推送结果：{}", importLogHistory.getImportStatus());
            }*/
            importLogHistoryService.updateById(importLogHistory);
        }
    }

    /**
     * 指令如果推送失败重复推送，加上初始化推送的，总共推送三次
     *
     * @param pushSubSystem
     * @param dtoJson
     * @param importLogHistory
     */
    private ImportLogHistory pushFailRepeatPush (PushSubSystem pushSubSystem, String dtoJson, ImportLogHistory importLogHistory) {
        String result = null;
        try {
            //推送子系统
            result = HttpClientUtil.postJson(pushSubSystem.getUrl(), null, dtoJson, pushSubSystem.getSocketTimeOut());
        } catch (Exception e) {
            importLogHistory.setImportStatus("error");
            importLogHistory.setImportNote(null == e.getMessage() ? null : e.getMessage());
            LOGGER.error("指令推送子系统：{}，地址：{}，失败！原因：{},参数：{}", pushSubSystem.getCode(), pushSubSystem.getUrl(), result, dtoJson);
        }
        if (!StringUtils.isEmpty(result)) {
            RestfulResponse restfulResponse = new RestfulResponse<>(0, "成功", null);
            try {
                restfulResponse = JSON.parseObject(result,
                        new TypeReference<RestfulResponse>() {
                        });
            } catch (Exception ex) {
                importLogHistory.setImportStatus("error");
                importLogHistory.setImportNote(null == ex.getMessage() ? null : ex.getMessage());
                restfulResponse.setCode(-1);
                restfulResponse.setMessage(ex.getMessage());
            }

            if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
                importLogHistory.setImportStatus("success");
                LOGGER.info("指令推送子系统：{}，地址：{}，成功！参数：{},返回值:{}",
                        pushSubSystem.getName(), pushSubSystem.getUrl(), dtoJson,result);
            } else if(Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 10){
                importLogHistory.setImportStatus("success");
                importLogHistory.setImportNote(null == restfulResponse.getMessage() ? null : restfulResponse.getMessage());
                LOGGER.info("指令推送子系统：{}，地址：{}，成功！参数：{},返回值:{}",
                        pushSubSystem.getName(), pushSubSystem.getUrl(), dtoJson,result);
            } else {
                importLogHistory.setImportStatus("error");
                importLogHistory.setImportNote(null == restfulResponse.getMessage() ? null : restfulResponse.getMessage());
                LOGGER.error("指令推送子系统：{}，地址：{}，失败！原因：{},参数：{},返回值:{}",
                        pushSubSystem.getName(), pushSubSystem.getUrl(), restfulResponse.getMessage(), dtoJson,result);
            }
        } else {
            importLogHistory.setImportStatus("error");
            importLogHistory.setImportNote("返回值为空！");
            LOGGER.error("指令推送子系统：{}，地址：{}，失败！参数：{},返回值:{}", pushSubSystem.getName(), pushSubSystem.getUrl(), dtoJson,result);
        }
        return importLogHistory;
    }


    private List<PushSubSystem> listPushSubSystem(String type) {
        Wrapper<PushSubSystem> ew = new EntityWrapper<>();
        ew.eq("type", type);
        return this.selectList(ew);
    }

    @Override
    public void pushOrderShipmentTms(String sourceKey) {
        Wrapper<ImportLogHistory> ew = new EntityWrapper<ImportLogHistory>();
        ew.eq("source_sys", "otm");
        ew.eq("source_key", sourceKey);
        ew.eq("type", IntegrationURIEnum.SHIPMENT_PUSH.getCode());
        ew.eq("target_sys","OMS");
        ew.orderBy("gmt_create",false);
        List<ImportLogHistory> importLogHistorys = importLogHistoryService.selectList(ew);
        if(null != importLogHistorys && !importLogHistorys.isEmpty()){
            ImportLogHistory importLogHistory = importLogHistorys.get(0);
            if("success".equals(importLogHistory.getImportStatus())){
                throw new BaseException("最新一条数据推送成功不能重复推送！");
            }
        }

        Date startDate = new Date();
        String shipmentXml = otmShipmentService.getOrderStringXML(sourceKey);
        ShipmentDTO shipmentDTODto;
        try {
            shipmentDTODto = transitionData(shipmentXml);
        } catch (BaseException ex) {
            throw ex;
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        List<PushSubSystem> pushSubSystemList = listOrderPushSubSystem(IntegrationURIEnum.SHIPMENT_PUSH.getCode(),"OMS");
        String dtoJson = JSON.toJSONString(shipmentDTODto);
        toSonSys(IntegrationURIEnum.SHIPMENT_PUSH.getCode(), startDate, shipmentXml, sourceKey, pushSubSystemList, dtoJson, shipmentDTODto.getSenderTransmissionNo());
    }

    public ShipmentDTO transitionData(String shipmentXml) throws Exception {
        ShipmentDTO shipmentDTODto;
        String strData = disposeXMLData(shipmentXml);
        shipmentDTODto = OtmShipmentParse.parse(strData);
        if (Objects.isNull(shipmentDTODto)) throw new BaseException("OTM指令数据转换错误！");
        return shipmentDTODto;
    }

    private List<PushSubSystem> listOrderPushSubSystem(String type,String code) {
        Wrapper<PushSubSystem> ew = new EntityWrapper<>();
        ew.eq("type", type);
        ew.eq("code", code);
        return this.selectList(ew);
    }

    @Override
    public void pushOrderShipmentWms(String sourceKey) {

        Wrapper<ImportLogHistory> ew = new EntityWrapper<ImportLogHistory>();
        ew.eq("source_sys", "otm");
        ew.eq("source_key", sourceKey);
        ew.eq("type", IntegrationURIEnum.SHIPMENT_PUSH.getCode());
        ew.eq("target_sys","WMS");
        ew.orderBy("gmt_create",false);
        List<ImportLogHistory> importLogHistorys = importLogHistoryService.selectList(ew);
        if(null != importLogHistorys && !importLogHistorys.isEmpty()){
            ImportLogHistory importLogHistory = importLogHistorys.get(0);
            if("success".equals(importLogHistory.getImportStatus())){
                throw new BaseException("最新一条数据推送成功不能重复推送！");
            }
        }

        Date startDate = new Date();
        String shipmentXml = otmShipmentService.getOrderStringXML(sourceKey);
        ShipmentDTO shipmentDTODto;
        try {
            shipmentDTODto = transitionData(shipmentXml);
        } catch (BaseException ex) {
            throw ex;
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        List<PushSubSystem> pushSubSystemList = listOrderPushSubSystem(IntegrationURIEnum.SHIPMENT_PUSH.getCode(),"WMS");
        String dtoJson = JSON.toJSONString(shipmentDTODto);
        toSonSys(IntegrationURIEnum.SHIPMENT_PUSH.getCode(), startDate, shipmentXml, sourceKey, pushSubSystemList, dtoJson, shipmentDTODto.getSenderTransmissionNo());
    }

    public String disposeXMLData(String shipmentXml) {
        return shipmentXml.replaceAll(" xmlns=\"http://xmlns.oracle.com/apps/otm/transmission/v6.4\"", "")
                .replaceAll(" xmlns:gtm=\"http://xmlns.oracle.com/apps/gtm/transmission/v6.4\" " +
                        "xmlns:otm=\"http://xmlns.oracle.com/apps/otm/transmission/v6.4\"", "")
                .replaceAll(" xsi:type=\"otm:TransactionHeaderType\"", "").replaceAll("otm:", "");
    }



    @Override
    public void queryShipmentToWms () {
        //1、查询前一天integration下发数据
        int current = 1;
        Page<ImportLogHistory> page = new Page<>();
        page.setSize(200);
        while (true){
            page.setCurrent(current++);
            List<ImportLogHistory> importLogHistories = importLogHistoryMapper.queryShipmentToWms(page);
            if (CollectionUtils.isEmpty(importLogHistories)) {
                break;
            }
            List<String> integrationList = new ArrayList<>();
            for (ImportLogHistory importLogHistory : importLogHistories) {
                integrationList.add(importLogHistory.getSourceKey());
            }

            //2、查询指令信息是否已经下发至wms
            String wmsQtyUrl = getTmsQtyUrl("WMS", "90501");
            List<String> wmsList = this.getWmsShipmentList(integrationList,wmsQtyUrl);

            //3、对比 integrationList 和 wmsList，wmsList 没有下发的结果为 compareList
            List<String> compareList = this.getCompareList(integrationList, wmsList);

            //4、解析七牛文件
            try{
                this.analysisQiNiuFileBySourceKey(compareList,IntegrationURIEnum.SHIPMENT_PUSH.getCode(), "WMS");
            }catch (Exception e){
                LOGGER.info("补发指令推送失败{},原因为{}",compareList,e.getMessage());
            }
        }

    }

    @Override
    public void pushShipmentToTms () {
        //1、查询前一天integration下发数据
        int current = 1;
        Page<ImportLogHistory> page = new Page<>();
        page.setSize(200);
        while (true){
            page.setCurrent(current++);
            List<ImportLogHistory> importLogHistories = importLogHistoryMapper.queryShipmentToTms(page);
            if (CollectionUtils.isEmpty(importLogHistories)) {
                break;
            }
            List<String> integrationList = new ArrayList<>();
            for (ImportLogHistory importLogHistory : importLogHistories) {
                integrationList.add(importLogHistory.getSourceKey());
            }

            //2、查询指令信息是否已经下发至wms
            String tmsQtyUrl = getTmsQtyUrl("TMS", "209");
            List<String> tmsist = this.getWmsShipmentList(integrationList, tmsQtyUrl);

            //3、对比 integrationList 和 wmsList，wmsList 没有下发的结果为 compareList
            List<String> compareList = this.getCompareList(integrationList, tmsist);

            //4、解析七牛文件
            try{
                this.analysisQiNiuFileBySourceKey(compareList,IntegrationURIEnum.SHIPMENT_PUSH.getCode(), "OMS");
            }catch (Exception e){
                LOGGER.info("补发指令推送失败{},原因为{}",compareList,e.getMessage());
            }
        }
    }

    /**
     * 解析七牛并重新推送
     */
    private void analysisQiNiuFileBySourceKey (List<String> compareList, String code, String sysCode) {
        for (String sourceKey : compareList) {
            Date startDate = new Date();
            String shipmentXml = otmShipmentService.getOrderStringXML(sourceKey);
            if(org.apache.commons.lang3.StringUtils.isEmpty(shipmentXml)){
                LOGGER.info("七牛文件解析为空！");
                return;
            }
            ShipmentDTO shipmentDTODto;
            try {
                shipmentDTODto = transitionData(shipmentXml);
            } catch (BaseException ex) {
                throw ex;
            } catch (Exception e) {
                throw new BaseException(e.getMessage());
            }
            List<PushSubSystem> pushSubSystemList = listOrderPushSubSystem(IntegrationURIEnum.SHIPMENT_PUSH.getCode(), sysCode);
            String dtoJson = JSON.toJSONString(shipmentDTODto);
            toSonSys(IntegrationURIEnum.SHIPMENT_PUSH.getCode(), startDate, shipmentXml, sourceKey, pushSubSystemList, dtoJson, shipmentDTODto.getSenderTransmissionNo());
        }
    }



    /**
     * 对比需要重新下发的指令
     */
    private List<String> getCompareList (List<String> integrationList, List<String> wmsList) {
        if (CollectionUtils.isEmpty(wmsList)) {
            return integrationList;
        }
        List<String> compareList = new ArrayList<>();
        for (String sourkey : integrationList) {
            if (!wmsList.contains(sourkey)) {
                compareList.add(sourkey);
            }
        }
        return compareList;
    }


    /**
     * 查询wms指令下发情况
     */
    private List<String> getWmsShipmentList (List<String> integrationList, String pushUrl) {
        List<String> list = new ArrayList<>();
        String jsonParam = JSONArray.toJSONString(integrationList);
        LOGGER.info("查询指令下发至{}的jsonParam为：{}", pushUrl, jsonParam);
        String postJson = HttpClientUtil.postJson(pushUrl, null, jsonParam, 100000);
        RestfulResponse<List<String>> restfulResponse = JSON.parseObject(postJson, new TypeReference<RestfulResponse<List<String>>>() {
        });
        if (Objects.nonNull(restfulResponse) && restfulResponse.getCode() == 0) {
            list = restfulResponse.getData();//把字符串转换成集合
            LOGGER.info("查询指令下发至{} 的结果：{}", pushUrl, list);
        }
        return list;
    }

    /**
     * 获取url
     */
    private String getTmsQtyUrl (String system,String systemCode) {
        EntityWrapper<PushSubSystem> ew = new EntityWrapper<>();
        ew.eq("code", system);
        ew.eq("TYPE", systemCode);
        List<PushSubSystem> pushSubSystem = pushSubSystemMapper.selectList(ew);
        if (CollectionUtils.isEmpty(pushSubSystem)) {
            throw new BaseException("调用系统的请问路径未配置！");
        }
        return pushSubSystem.get(0).getUrl();
    }

    @Override
    public void saveShipmentLog(Object dto, String type,Date startDate,String shipmentXml,String shipmentId, Long senderTransmissionNo) {
        if (Objects.isNull(dto)) throw new BaseException("数据不能为空！");
        List<PushSubSystem> pushSubSystemList = listPushSubSystem(type);
        String dtoJson = JSON.toJSONString(dto);
        saveShipmentLogSubsys(type, startDate, shipmentXml, shipmentId, pushSubSystemList, dtoJson, senderTransmissionNo);
    }

    public void saveShipmentLogSubsys(String type, Date startDate, String shipmentXml, String shipmentId, List<PushSubSystem> pushSubSystemList, String dtoJson, Long transmissionNo) {
        for (PushSubSystem pushSubSystem : pushSubSystemList) {
            Date endDate;
            endDate = new Date();
            ImportLogHistory importLogHistory = new ImportLogHistory();
            importLogHistory.setTargetSys(pushSubSystem.getCode());
            importLogHistory.setSourceSys("otm");
            importLogHistory.setSourceKey(shipmentId);
            importLogHistory.setType(type);
            importLogHistory.setImportStartTime(startDate);
            importLogHistory.setImportEndTime(endDate);
            importLogHistory.setTransmissionNo(transmissionNo);
            LOGGER.info("开始保存导入日志---------------");
            otmShipmentService.updateLogHistory(importLogHistory, shipmentXml);
            LOGGER.info("完成日志保存---------------");

            importLogHistoryService.updateById(importLogHistory);
        }
    }

    @Override
    public void pushNewShipment() {
        //1、查询前三分钟integration下发数据
        int current = 1;
        Page<ImportLogHistory> page = new Page<>();
        page.setSize(500);
        page.setCurrent(current++);
        List<ImportLogHistory> importLogHistories = importLogHistoryMapper.queryNoPushShipment(page);
        if (CollectionUtils.isEmpty(importLogHistories)) {
            return;
        }

        List<PushSubSystem> pushSubSystemList = listPushSubSystem(IntegrationURIEnum.SHIPMENT_PUSH.getCode());

        for (ImportLogHistory importLogHistory : importLogHistories) {
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(importLogHistory.getDataStorageKey())) {
                //解析七牛文件
                String shipmentXml = otmShipmentService.getOrderStringXMLByKey(importLogHistory.getDataStorageKey());
                ShipmentDTO shipmentDTODto;
                try {
                    shipmentDTODto = transitionData(shipmentXml);
                } catch (BaseException ex) {
                    throw ex;
                } catch (Exception e) {
                    throw new BaseException(e.getMessage());
                }
                String dtoJson = JSON.toJSONString(shipmentDTODto);

                if ("WMS".equals(importLogHistory.getTargetSys())) {
                    if (CollectionUtils.isNotEmpty(pushSubSystemList)) {
                        for (PushSubSystem pushSubSystem : pushSubSystemList) {
                            if ("WMS".equals(pushSubSystem.getCode())) {
                                this.pushToSonSys(pushSubSystem, dtoJson, importLogHistory);
                            }
                        }
                    }
                } else if ("OMS".equals(importLogHistory.getTargetSys())) {
                    if (CollectionUtils.isNotEmpty(pushSubSystemList)) {
                        for (PushSubSystem pushSubSystem : pushSubSystemList) {
                            if ("OMS".equals(pushSubSystem.getCode())) {
                                this.pushToSonSys(pushSubSystem, dtoJson, importLogHistory);
                            }
                        }
                    }
                }
            }
        }

    }

    /**
     * 指令下发失败，重新推送，加上第一次推送，总共需要推送三次
     * 更新子系统返回状况
     */
    private void pushToSonSys(PushSubSystem pushSubSystem, String dtoJson, ImportLogHistory importLogHistory) {
        this.pushFailRepeatPush(pushSubSystem, dtoJson, importLogHistory);
        if (StringUtils.isEmpty(importLogHistory.getTargetSys()) || null == importLogHistory.getTransmissionNo())
            return;
        importLogHistoryMapper.updateImpResultByTranNo(importLogHistory.getTargetSys(), importLogHistory.getTransmissionNo(), importLogHistory.getImportStatus(), importLogHistory.getImportNote());
        //                                importLogHistoryService.updateById(importLogHistory);
    }

}
